home *** CD-ROM | disk | FTP | other *** search
- ;------------------------------------------------------------------------------;
- ; ;
- ; Switch Directory - SD Copyright (c) Stephen M. Falatko, 1987 ;
- ; ;
- ; Switch Directory (SD) is a utility that allows easy switching ;
- ; between subdirectories and drives with a minimum of typing. SD ;
- ; has been designed to replace the DOS CD command and provide ;
- ; enhancements to the CD command. SD allows you to specify a ;
- ; specific subdirectory name, a combination of subdirectory names ;
- ; and search switches or a complete path specifier. All features of ;
- ; SD work across disk drives. If you have made a mistake, hitting ;
- ; Ctrl-Brk while SD is searching will break you out of SD and put ;
- ; you back in the subdirectory you started in. With version 3.0 SD ;
- ; will also except a 'minimum match' to a subdirectory name (i.e. if ;
- ; you have only one directory that begins with 'LO' then SD LO will ;
- ; take you there even if the full name is LOTUS). Given a full path ;
- ; designation, SD switches to the specified path without searching. ;
- ; An important feature of SD is that it can be enqueued to PCED, the ;
- ; DOS Command EDitor by Chris Dunford (and its public domain ;
- ; counterpart CED. When enqueued SD will seem like and extension of ;
- ; DOS. In this configuration SD dos NOT have to be present anywhere ;
- ; on your disk drives. ;
- ; ;
- ; ;
- ;Usage ;
- ; ;
- ; [d:\....]>SD [drive][command specification] ;
- ; ;
- ; [drive] - the drive to search. (if not searching the current drive) ;
- ; ;
- ; [command specification] ;
- ; ;
- ; - this can be any valid CD command or any combination of \ ;
- ; (for specific paths) or / (for search below the current ;
- ; dir) (if blank SD returns the current path). ;
- ; ;
- ; A valid command could be: ;
- ; ;
- ; SD c:\turbo/source\myprog ;
- ; ;
- ; This would switch to c:\turbo then search its subdirectories for ;
- ; a source subdirectory then switch to the myprog subdirectory. ;
- ; If no \ or / is specified then the entire disk is searched for ;
- ; the desired subdirectory starting with the current directory. ;
- ; ;
- ; Special Command: SD [c will enqueue SD to the CED program (p for PCED) ;
- ; SD [c+ will enqueue SD without online help. ;
- ; ;
- ; ;
- ; ;
- ;The source code was originally developed from Vern Buerg's LDIR program and ;
- ;Charles Wooster's WHISK program. PrintS and GetDir are Copyrighted by there ;
- ;authors. ;
- ; ;
- ;6/04/87 - Stephen Falatko ;
- ; ;
- ;Written for the A86 assembler (All numbers with leading 0 are hex) ;
- ; ;
- ;------------------------------------------------------------------------------;
-
-
- ;---------------------------------------------------------------------------;
- ; ;
- ; Macros and Equates ;
- ; ;
- ;---------------------------------------------------------------------------;
-
-
- LF Equ 10
- CR Equ 13
- Stopper Equ 255 ;Ends print strings
-
- ;
- ; These equates are for DOS functions. They are all in hex. A86 defaults
- ; to hex if the number has a leading 0.
- ;
-
- SetDrive Equ 0E
- CurrentDisk Equ 019 ;Get current disk
- SetDTA Equ 01A ;Set data transfer area
- ChangeDir Equ 03B ;Change directory
- GetPath Equ 047 ;Get current directory
-
-
- Change_Dir MACRO
-
- Mov DX,Offset #1
- Mov AH,ChangeDir
- Int 021
- #EM
-
- Set_Drive MACRO
-
- Mov AH,SetDrive
- Int 021
- #EM
-
- Get_Path MACRO
-
- Mov AH,GetPath
- Int 021
- #EM
-
- Current_Disk MACRO
-
- Mov AH,CurrentDisk
- Int 021
- #EM
-
- ;---------------------------------------------------------------------------;
- ; ;
- ; Here is where the code begins ;
- ; ;
- ;---------------------------------------------------------------------------;
-
- CODE SEGMENT
-
- Org 0100
- Main:
- Jmp Start
-
- ;---------------------------------------------------------------------------;
- ; ;
- ; Data Areas, Constants, Etc. ;
- ; ;
- ;---------------------------------------------------------------------------;
-
- Version Db CR,'Switch Directory 3.0',CR,LF
- Copyright Db 'Copyright (c) 1987 by Stephen M. Falatko',CR,LF
- FakeEOF Db 26
-
- Errlvl Db 0 ;DOS return code
-
- ;
- ; These are flags set by the command line processing
- ;
- ;
-
- RootFlag Db 0 ; signal indicating default to root (0)
- CDFlag Db 0 ; signal of specific path (1)
- OneDeepFlag Db 0 ; search only current dir (1)
-
- ;
- ; This flag is set to indicate that a subdirectory has been found (ie if its
- ; 0 at the end then we did not find the subdirectory)
- ;
-
- Done_Flag Db 0 ; found subdir during search
-
- ;
- ; This flag is set if SD is enqueued to CED
- ;
-
- CEDFlag Db 0
-
- ;
- ; If this flag is set then help is available if ? is entered on the
- ; command line
- ;
-
- HelpFlag Db 1
-
- ;
- ; These variables hold the systems Ctrl-Break address so we can restore
- ; it when we exit
- ;
-
- CtrlBrkOff Dw 0
- CtrlBrkSeg Dw 0
-
- ;
- ; Here we will store the desired subdirectory (and drive if selected)
- ; as well as the original path and drive
- ;
-
- Sub_Dir Db 63 Dup (0) ; The sub dir we want to change to
-
- ScratchDirStart Db 'x:\' ; This is a scratch area for the
- ScratchDir Db 63 Dup (0) ; GetDir function
-
- OrigDr Db 'x:' ; Original drive
- OrigDir Db '\',63 Dup (0) ; and path
-
- RootDir Db 'x:\',0 ; To get vol label
-
- Count Dw 0 ; Number of args on command line
-
- ;
- ; These variables are used by the search routine
- ;
-
- DtaPointer Dw DtaAreaBegin ; Pointer to our DTA area
- Direction Db 0 ; Flag to indicate search subdirs
- ; of the current dir or not
- BackOneDir Db '..',0 ; Asciiz 'filename' to backup
- ; one directory
- SearchAsciiZ Db '*.*',0 ; Search filename
-
- ;
- ; Error messages
- ;
-
- NoHelp Db CR,LF,'ERROR - Installed without help',CR,LF,Stopper
-
- ErrorMsgs Db CR,LF,'Illegal drive specifier - must be A to z',CR,LF,Stopper
- Db CR,LF,'Maximum of 64 characters on command line',CR,LF,Stopper
- Db CR,LF,'Illegal character on command line ',CR,LF,Stopper
- Db CR,LF,'Currently in root directory ',CR,LF,Stopper
- Db CR,LF,'Command line contains an invalid path ',CR,LF,Stopper
- Db CR,LF,'Subdirectory Not Found ',CR,LF,Stopper
-
- Start:
- ;
- ; If we are enqueued as a CED command we must preserve the DS register
- ; and null out the CED internal command line. (When we leave we don't
- ; want DOS to do anything)
- ;
- CS Cmp CEDFlag,1 ; Enqueued to CED ?
- Jne NoCED
-
- Mov B [SI],CR ; Null out the CED Buffer for our exit
- Mov BP,DX ; save pointer to CED internal buffer
-
- Mov ES,DS ; This saves the DS value if we are
- ; enqueued to CED (points to CED internal
- ; buffer)
- Mov DS,CS ; make sure our data is from this segment
- ;
- ; If we are not enqueued to CED then we merely call setup
- ;
- NoCED:
- Call SetUP ; Save current drive and path, reset drive
- ;
- ; We begin by determining if there are any command line arguments. If we
- ; are enqueued to CED then we see if the first character in the buffer is a
- ; carriage return. If we are running from DOS then we look in the PSP for the
- ; command line count.
- ;
- Cmp CEDFlag,1
- Jne Not_Enqueued_To_CED
- ;
- ; Nothing but CR on command line? If so show path and leave
- ;
- CED_CR_Check:
- ES Mov AL,B [BP] ; Any characters on the command line?
- Inc BP
- Cmp AL,' '
- Je CED_CR_Check
- Cmp AL,CR
- Je No_Parameters ; no so go set to root and leave
-
- ;
- ; The first character wasn't a CR so let's find out how many characters
- ; are on the command line and go process them.
- ;
- Mov CX,64 ; assume 64 characters on command line
- Mov BX,CX ; save CX in BX
- Mov AL,CR ; want to find CR
- Mov DI,BP ; point DI to CED command line
-
- Repne Scasb ; scan for CR
- Jcxz Too_Many_Characters
-
- Sub BX,CX ; calculate number of chars on command line
- Mov CX,BX
-
- Jmp Short Got_Parameters ; go process them
-
- Too_Many_Characters:
-
- Mov Errlvl,2 ; signal error type (too many characters)
- Jmp Error_Found
- ;
- ; If we are not enqueued to CED we get the number of chars from the PSP
- ;
- Not_Enqueued_To_CED:
-
- Sub CX,CX ; Clear CX
- Mov CL,B [080] ; Get the number of characters on the
- ; command line (from the PSP)
-
- Cmp CX,64 ; more than 64 characters not allowed
- Ja Too_Many_Characters
-
- Cmp CX,0 ; Anything on the command line?
- Jne Got_Parameters
- ;
- ; If we find nothing then we show the current path and leave
- ;
- No_Parameters:
-
- Call ShowPath ; set root dir and leave
- Jmp Exit
- ;
- ; We have found some parameters so we processes them.
- ;
- Got_Parameters:
-
- Call CommandLine
- ;
- ; If the carry flag is set when we exit CommandLine we were unsuccessful
- ;
- Jc Error_Found
- ;
- ; If Done_Flag is set then we were successful, we're finished and we can leave
- ;
- Cmp Done_Flag,1
- If e Jmp Exit
- ;
- ; If we return from CommandLine with CDFlag set that indicates that a
- ; specific path has been selected and we switch to that specified path.
- ; Otherwise we search for the desired subdirectory
- ;
- Cmp CDFlag,1
- Jne Look_For_The_Subdir
-
- Call SetPath
- ;
- ; If the carry flag is set upon return from SetPath the path does not
- ; exist and we display the not found message and return to the starting point
- ; otherwise we're through and we can leave
- ;
- If nc Jmp Short Exit
- Mov Errlvl,5 ; signal error type (invalid path)
- Jmp Short Error_Found
- ;
- ; Now if CDFlag was not set we must search for the subdir. We will begin by
- ; searching the current directory (like the CD command) and then, if required,
- ; we'll search the rest of the disk.
- ;
- Look_For_The_Subdir:
-
- Mov OneDeepFlag,1 ; search current level
- Call GetDir ; Read the directory
- ;
- ; Now, we reset OneDeepFlag just in case and see if we were successfull
- ;
- Mov OneDeepFlag,0 ; reset OneDeepFlag
- Cmp Done_Flag,1 ; did we find it?
- Je Exit ; found it so leave
- ;
- ; If we were not successful searching the current directory then we search
- ; more of the disk. (if rootflag is set then we search the whole disk,
- ; otherwise we search only the subordinate directories.
- ;
- Cmp RootFlag,1 ; default to the root directory?
- If ne Call No_Arg ; if not equal set to root for search
- Call GetDir ; Read the directory
- ;
- ; If Done_Flag is set then we have been successful, otherwise we did not
- ; find the desired subdirectory.
- ;
- Cmp Done_Flag,1
- Je Exit
-
- Mov Errlvl,6 ; signal error type (subdir not found)
- Jmp Short Error_Found
- ;
- ; If we make it here we have not found the subdirectory so we tell the user
- ; and return them to the starting drive:subdirectory.
- ;
- Error_Found:
- ;
- ; We begin by sending a message to the user
- ;
- Xor AX,AX ; clear AX
- Mov DX,Offset ErrorMsgs ; point to the beginning of the error msgs
- Mov AL,Errlvl ; which error?
- Dec AX ; decrement for position
- Mov CX,45 ; characters per message
- Mul CL ; times error type-1
- Add DX,AX ; point to it
- Call PrintS
-
- ;
- ; Now we reset the drive if it has been changed. NOTE: A Ctrl+Brk during
- ; processing will come here and the user will be returned home (so to speak)
- ;
- NFCB:
- Sub DX,DX ; clear DX
- Mov DL,OrigDr ; get original drive
- Cmp DL,RootDir ; compare with current drive
- ;
- ; If the selected directory does not match the original directory reset
- ;
- Je Same_Drive
-
- Sub DL,'A' ; change DL from ascii
- Set_Drive ; Macro...
- ;
- ; Now we reset to our original path and leave
- ;
- Same_Drive:
-
- Change_Dir OrigDr ; Set path to original path (Macro...)
-
- Exit:
- ;
- ; Now, if we are enqueued to CED we leave with a far return, otherwise
- ; we exit with DOS function 4C.
- ;
- Cmp CEDFlag,1 ; enqueued to CED
- Jne ExitDOS
-
- Mov RootFlag,0 ; reset flags for next time
- Mov CDFlag,0
- Mov OneDeepFlag,0
- Mov Done_Flag,0
-
- Mov DtaPointer,offset DtaAreaBegin ; reset pointer to our DTA
-
- Mov ES,CS ; clear out start of DTA
- Mov DI,[DtaPointer]
- Mov AX,0
- Mov CX,43
-
- Dta_Clear:
-
- Stosw
- loop Dta_Clear
- ;
- ; During the Setup procedure we took over the Ctrl-Break address
- ; so now we restore it.
- ;
- Mov DX,CtrlBrkOff ; Ctrl-Break offset
- Mov DS,CtrlBrkSeg ; Ctrl-Break segment
- Mov AH,025 ; set interrupt vector
- Int 021
-
- RetF ; yes, exit with far return
-
- ExitDOS:
- Mov AL,Errlvl ; Return to system
- Mov AH,04C ; via EXIT
- Int 021
-
- ;---------------------------------------------------------------------------;
- ; No_Arg ;
- ; ;
- ; No_Arg resets the current path to the root directory. ;
- ; ;
- ;---------------------------------------------------------------------------;
-
- No_Arg:
- ; If no argument then set current
- Change_Dir RootDir ; path to root directory
-
- Ret
-
- ;---------------------------------------------------------------------------;
- ; SetUp ;
- ; ;
- ; SetUp initializes some variables and resets the disk drives ;
- ; ;
- ;---------------------------------------------------------------------------;
-
- SetUp:
- Push DX,ES,DS
-
- ;
- ; We begin with a disk reset
- ;
- Mov AH,0D ; Reset diskettes
- Int 021
- ;
- ; Now we call DOS for the current disk drive and store the information
- ; as an ascii drive specifier in several variables for future use
- ;
- Current_Disk ; Get current disk (Macro...)
-
- Add AL,'A'
- Mov OrigDr,AL ; Save original drive letter
- Mov RootDir,AL ;
- Mov ScratchDirStart,AL
- ;
- ; We also want to store our current path so we can return if necessary
-
- Mov DL,OrigDr ; put original drive in DL
- Sub DL,'@' ; convert from ascii character
- Mov SI,Offset OrigDir + 1 ; the original drive
- Get_Path ; Macro...
- ;
- ; Our last task is to point the Ctrl+Break vector to our Not_Found code
- ; so the user is left where they began if using Ctrl+Break. But first we
- ; store the current Ctrl-Brk vector so we can restore it when we leave
- ;
- Mov AX,03523 ; call DOS for Ctrl-Break location
- Int 021
- Mov CtrlBrkSeg,ES
- Mov CtrlBrkOff,BX
- ;
- ; Now let's set up our Ctrl-Brk.
- ;
- Mov AX,02523 ; set Ctrl+Break vector to point
- Mov DX,Offset CtrlBrk ; to our not found. This way a Ctrl+Brk
- Int 021 ; will leave us in the place we started
-
- Pop DS,ES,DX
- Ret
-
- ;---------------------------------------------------------------------------;
- ; CommandLine ;
- ; ;
- ; CommandLine parses the command line, looking for switches and sub- ;
- ; dir names ;
- ; ;
- ;---------------------------------------------------------------------------;
-
- CommandLine:
- ;
- ; We begin by setting DI and defaulting SI to the PSP
- ;
- Mov SI,081 ; point SI to the beginning of the
- ; command line
- ;
- ; If we are Enqueued to CED then we want SI to point to BP-1.
- ;
- Cmp CEDFlag,1 ; enqueued to CED
- Jne Set_DI ; nope, go on
- Dec BP ; decrement BP
- Mov SI,BP ; mov BP to SI
- ;
- ; Now setup DI
- ;
- Set_DI:
-
- Mov DI,Offset Sub_dir ; point DI to our internal buffer for
- ; the desired sub directory name
- ;
- ; Now, we want to scan the command line to see if a drive was specified
- ; We do this by looking for a ':' character. (remember cx holds the number
- ; of parameters)
- ;
- Push DI ; save DI
- Mov DI,SI
- Mov al,':' ; we'll look for a ':'
- Repne Scasb
- ;
- ; Just to be sure we found a character and not the end of the line we peek
- ; at the position immediately before the current DI position
- ;
- ES Cmp B [DI-1],':' ; did we find one or are we at the end
- ; of the command line? (the segment
- ; override is needed if enqueued to CED)
- Jne Clean_Up ; if we did not find a ':' the go on
- ;
- ; If we did find a drive letter then we set SI to point to the char after ':'
- ;
- Mov SI,DI ; now, point SI to the character following
- ; the ':' character
- ;
- ; We now point DI to the drive letter and put it in AL
- ;
- Sub DI,2 ; point DI to the drive specifier
- ES Mov AL,B [DI] ; save the drive specifier in al - again
- ; the segment override is needed for CED)
- ;
- ; We must check the drive letter to see that it is a letter and then make sure
- ; it is capitalized
- ;
- Cmp AL,'A' ; compare with A
- If b Jmp DriveError ; if smaller then it is an erroneous drive
-
- Cmp AL,'z' ; compare with z
- If a Jmp DriveError ; if larger then it is an erroneous drive
-
- Cmp AL,'a' ; lowercase letter?
- Jb New_Drive? ; no its upper case so lets go on
- Xor AL,020 ; make upper case
- ;
- ; Now we have an uppercase drive letter we first check to see that it is
- ; different from the original drive if its not we go on.
- ;
- New_Drive?:
- Cmp OrigDr,AL
- Je Anything_Else_On_CLine?
- ;
- ; We have a different drive letter so lets store it and the change drives
- ;
- Mov RootDir,AL ; save new drive specifier
- Mov ScratchDirStart,AL
- ;
- ; After saving we call DOS and change the drive to the desired one
- ;
- Sub DX,DX ; clear dx
- Mov DL,AL ; must change drive to number, not ascii
- Sub DL,'A'
- Set_Drive ; Macro....
- ;
- ; To speed things up we look to see if there's anything but a CR on the
- ; command line.
- ;
- Anything_Else_On_CLine?:
-
- ES Cmp B [SI],' ' ; strip the spaces (ES override for CED)
- Jne Not_Blank ; not a blank, how about a CR?
- Inc SI ; increment SI to check the next character
-
- Jmp Short Anything_Else_On_CLine?
-
- Not_Blank:
-
- ES Cmp B [SI],CR ; found a CR?
- Jne Clean_Up ; if not go on
-
- Mov Done_Flag,1
- Pop DI ; get DI off stack
- Jmp ExitCL ; leave
-
- Clean_Up:
-
- Pop DI ; get DI off stack
-
- ;
- ; We've now found a drive if it has been specified and we're ready
- ; to look at the rest of the command line
- ;
- Parse_Command_Line:
-
- Mov DS,ES ; must play with segments incase enqueued
- ; to CED
- Lodsb ; get character from command line and
- ; put it in al
- Mov DS,CS
-
- Cmp AL,' ' ; strip leading blanks from the command
- Jz Parse_Command_Line ; line
-
- Cmp AL,CR ; is it a carriage return ?
- If e Jmp We_Are_Finished ; if so we're at the end so jump on
- ;
- ; We need to check and see if we are to be enqueued to CED
- ;
- Cmp AL,'[' ; found enqueue command?
- Jne Back_One? ; nope, go on
-
- Cmp DI,Offset Sub_Dir ; found it, is it the first character?
- If e Jmp CEDEnqueue ; yes then enqueue
- Stc ; no, error so leave
- Mov Errlvl,3 ; signal error type (illegal character)
- Jmp ExitCL
- ;
- ; If we find a '.' character we must check for '..' which CD uses
- ; to go back one level
- ;
- Back_One?:
-
- Cmp AL,'.'
- Jne Display_Help?
- ;
- ; We found one '.' but are there two?
- ;
- ES Cmp W [SI-1],'..' ; two periods?
- Je Go_Back_One ; if so back one dir.
- Stc ; if not error
- Mov Errlvl,3 ; signal error type (illegal character)
- Jmp ExitCL
-
- Go_Back_One:
-
- Change_Dir BackOneDir ; change back one
- Jnc Go_Back_One_Worked
- Mov Errlvl,4 ; signal error type (in root)
- Jmp ExitCL ; leave
-
- Go_Back_One_Worked:
-
- Mov Done_Flag,1 ; else set done_flag and leave
- Jmp ExitCL ; do a not so nice jump to exit
- ;
- ; If the help character (?) is the first character on the command line
- ; then we display the help message and leave
- ;
- Display_Help?:
-
- Cmp AL,'?' ; help character?
- Jne Search_Below?
-
- Cmp DI,Offset Sub_Dir ; is it the first character ?
- Jne Search_Below?
- ;
- ; Now that we have found the help character is help available?
- ;
- Cmp HelpFlag,1 ; help info loaded ?
- Je Show_Help ; yes so display it
- ;
- ; Help not available, display message.
- ;
- Mov DX,Offset NoHelp ; display error message and leave
- Call PrintS
- Mov Done_Flag,1
- Jmp ExitCL
-
- Show_Help:
-
- Mov DX,Offset Help ; yes, let's display the help screen and
- Call PrintS ; then leave
- Mov Done_Flag,1
- Jmp ExitCL
- ;
- ; The / switch indicates that we are only to search for subdirectories of
- ; the current directory. (This was changed in version 3.0 of SD)
- ;
-
- Search_Below?:
-
- Cmp AL,'/' ;search below (/) switch ?
- If ne Jmp Path_Specified?
- ;
- ; If we find this character we want to know if its the first character of the
- ; command line or not.
- ;
- Cmp DI,Offset Sub_Dir ; have we stored any characters yet?
- Jne SB_Not_First_Char
- ;
- ; If it is the first we set a flag to keep us from defaulting to the
- ; root directory before we search
- ;
- Mov RootFlag,1 ; signal to search below, not reset to
- Jmp Short Parse_Command_Line ; root
- ;
- ; Now, if its not the first character on the command line we need to
- ; do some fancy footwork. First we need to see if a specific path
- ; has previously been signaled.
- ;
- SB_Not_First_Char:
-
- Cmp CDFlag,1 ; have we already seen a specific
- ; path on the command line?
- Jne SB_No_Path_Yet ; no so go on
- ;
- ; A specific path has been previously selected so we make this path an
- ; asciiz string and switch to it. Upon completion we reset DI to the
- ; begining of our command line buffer and clear the specific subdir flag.
- ;
- Mov B [DI],0 ; make current path asciiz string
- Call SetPath ; change to the already specified path
- ;
- ; If the carry flag is set there was an error in the path (usually it didn't
- ; exist)
- ;
- Jnc SB_Not_First_Char_Done ; if the subdir doesn't exist leave
- Mov Errlvl,5 ; signal error type (invalid path)
- Jmp ExitCL ; leave
- ;
- ; If the path existed then we reset DI to the beginning of our buffer,
- ; reset CDFlag and set RootFlag.
- ;
- SB_Not_First_Char_Done:
-
- Mov DI,Offset Sub_Dir ; reset DI
- Mov CDFlag,0 ; clear specific subdir flag
- Mov RootFlag,1 ; search below, don't default to root
- Jmp Short Parse_Command_Line ; go get next char
- ;
- ; It hasn't so this means that we search the disk for the subdir specified
- ; up till now (on the command line). To do this we must make the name an
- ; asciiz string, search for it then specify that we don't want to default
- ; to the root directory before out next search. DI must also be reset.
- ; In doing the search we imitate the CD command by first searching the current
- ; level and then enhance it by searching the whole disk (if RootFlag set,
- ; otherwise search only below current dir)
- ;
- SB_No_Path_Yet:
-
- Mov B [DI],0 ; make current path asciiz string
- Mov Count,DI ; how many characters stored?
- Sub Count,Offset Sub_Dir ; we need to set this for GetDir
- ;
- ; Set OneDeepFlag so we only check current directory
- ;
- Mov OneDeepFlag,1 ; start by searching current level
- Call GetDir ; search for path already specified
- ;
- ; Reset OneDeepFlag, check to see if we are done and if so move on
- ;
- Mov OneDeepFlag,0 ; reset the OneDeepFlag
- Cmp Done_Flag,1 ; see if we were successful
- Je Search_A_Success ; if not leave
- ;
- ; ..otherwise re-search. We reset to the root directory if RootFlag is set
- ;
- Cmp RootFlag,1 ; searching only below?
- If ne Call No_Arg ; set to root for search
- Mov Count,DI ; how many characters stored?
- Sub Count,Offset Sub_Dir ; we need to set this for GetDir
- Call GetDir ; search for path already specified
- ;
- ; If Done_Flag is set then we have found our directory, otherwise we set
- ; the carry flag and leave
- ;
- Cmp Done_Flag,1 ; see if we were successful
- Je Search_A_Success ; if not leave
- Stc
- Mov Errlvl,6 ; signal error type (subdir not found)
- Jmp ExitCL
- ;
- ; We found the subdir, now reset Done_Flag for future use as well as DI
- ;
- Search_A_Success:
-
- Mov Done_Flag,0 ; reset Done_Flag incase of future searches
- Mov RootFlag,1 ; search below, don't default to root
- Mov DI,Offset Sub_Dir ; reset DI
- Jmp Short Parse_Command_Line
- ;
- ; The \ switch indicates a specific path is specified. (i.e. no searching
- ; just switch to this path.
- ;
- Path_Specified?:
-
- Cmp AL,'\' ; Path seperator/indicator (\) ?
- If ne Jmp Process_Character
- ;
- ; If we find this flag we want to know if its the first character of the
- ; command line or not.
- ;
- Cmp DI,Offset Sub_Dir ; still pointing to beginning?
- Jne PS_Not_First_Char
- ;
- ; If it is the first we set a flag to indicate a specific subdir has been
- ; selected.
- ;
- Change_Dir RootDir ; make sure we are at the root dir
- Mov CDFlag,1 ; set flag to select specific subdir
- ;
- ; Strip any leading blanks.....
- ;
- P1:
- ES Cmp B [SI],' ' ; strip any blanks
- Jne P2
- Inc SI
- Jmp Short P1
- ;
- ; If all that's left is a carriage return we are done, otherwise get the next.
- ;
- P2:
- ES Cmp B [SI],CR
- If ne Jmp Short Parse_Command_Line
- Mov Done_Flag,1
- Jmp ExitCL
- ;
- ; If its not the first character we check to see if another one has already
- ; been found.
- ;
- PS_Not_First_Char:
-
- Cmp CDFlag,1 ; already set to look for path?
- Je Already_Reading_Path ; yes so go on
- ;
- ; None has been found yet so we make the current string (in the buffer)
- ; an asciiz string and go search for the subdir it specifies. After
- ; the search we reset DI, Done_Flag and CDFlag.
- ;
- Mov B [DI],0 ; make string asciiz
- ;
- ; Set the character count and a flag to search the current level
- ;
-
- Mov Count,DI ; how many characters stored?
- Sub Count,Offset Sub_Dir ; we need to set this for GetDir
- Mov OneDeepFlag,1 ; start by searching current level
- Call GetDir ; search for path already specified
- ;
- ; Reset the OneDeepFlag and see if we found our subdir
- ;
- Mov OneDeepFlag,0 ; reset the OneDeepFlag
- Cmp Done_Flag,1 ; see if we were successful
- Je PS_Search_A_Success ; if not leave
- ;
- ; If we didn't find the dir we check to see if we reset to the root and
- ; continue on with the search.
- ;
- Cmp RootFlag,1 ; reseting to root ?
- If ne Call No_Arg ; set to root for search if flag not set
-
- Mov Count,DI ; how many characters stored?
- Sub Count,Offset Sub_Dir ; we need to set this for GetDir
- Call GetDir ; search for specified path
- ;
- ; We have searched the desired part of the drive, now did we find anything?
- ;
- Cmp Done_Flag,1 ; see if we were successful
- ;
- ; If we did we reset the flags and continue on, otherwise leave.
- ;
- Je PS_Search_A_Success ; if not leave
- Stc ; set carry flag to signal error
- Mov Errlvl,6 ; signal error type (subdir not found)
- Jmp Short ExitCL
-
- PS_Search_A_Success:
-
- Mov Done_Flag,0 ; reset Done_Flag incase of future searches
- Mov DI,Offset Sub_Dir ; reset DI
- Mov CDFlag,1 ; indicate specific path
- Jmp Short Parse_Command_Line
- ;
- ; If we have already seen a path seperator we continue building the
- ; desired path in our buffer.
- ;
- Already_Reading_Path:
-
- Push ES ; change segment registers. This is
- Mov ES,CS ; required if we are enqueued to CED
- Stosb
- Pop ES
- Jmp Short Parse_Command_Line ; and get next char
- ;
- ; Now we make sure the character is upper case because DOS doesn't like
- ; lower case. There is potential for error here because these checks will
- ; pass some invalid characters (for DOS filenames). The result is some
- ; delay before an error is found.
- ;
- Process_Character:
-
- Cmp AL,'!' ; compare with !
- If b Jmp Parse_Command_Line ; get next char if smaller
-
- Cmp AL,'z' ; compare with z
- If a Jmp Parse_Command_Line ; get next char if bigger
-
- Cmp AL,'a' ; lowercase letter?
- Jb Store_The_Character ; nope so go on
- Xor AL,020 ; make upper case
- ;
- ; Now we have an upper case character let's store it in our buffer and
- ; go get the next
- ;
- Store_The_Character:
-
- Push ES ; again, we have to change the segment
- Mov ES,CS ; registers to allow for CED
- Stosb
- Pop ES
-
- Jmp Short Parse_Command_Line
- ;
- ; When we get here we're done with the command line and we must make
- ; sure that we have an asciiz name in our buffer.
- ;
- We_Are_Finished:
-
- Mov Count,DI ; how many characters stored?
- Sub Count,Offset Sub_Dir
- ;
- ; If count is zero we have not found anything on the command line so let's
- ; reset to the root directory and leave
- ;
- Cmp Count,0
- Jne Something_In_Buffer
- ;
- ; Show the path
- ;
- Call ShowPath ; display the path
- Mov Done_Flag,1 ; signal done
- Jmp Short ExitCL ; leave
- ;
- ; We found something so let's make sure its an asciiz string
- ;
- Something_In_Buffer:
-
- Mov AL,0
- Push ES ; override the segment registers
- Mov ES,CS
- Stosb
- Pop ES
- Jmp Short ExitCL
- ;
- ; If an illegal drive was specified on the command line we come here and
- ; display and error message. The Done_Flag is then set and we return to
- ; the main program.
- ;
- DriveError: ; we come here if the drive specifier
- ; is not in A to z
- Pop DI
- Mov Errlvl,1
- Stc
-
- ExitCL:
- Ret
-
- ;---------------------------------------------------------------------------;
- ; GetDir ;
- ; ;
- ; GetDir searches for the desired subdirectory. The extent of the ;
- ; search can be modified by command line switches ;
- ; ;
- ; Based on WHISK by Charles Wooster ;
- ;---------------------------------------------------------------------------;
-
- GetDir:
- Push SI,DI,ES
- Mov ES,CS
-
- Mov Done_Flag,0
-
- ; Find first or next subdirectory level
- ; -------------------------------------
-
- NextLevel:
- Mov DX,[DTAPointer] ; Next nested DTA
- Mov AH,1Ah ; For DOS call to set DTA
- Int 21h ; Do it
-
- Cmp [Direction],0 ; Check if we're nesting
- Jnz FindNextFile ; If not, we're continuing
-
- Mov DX,Offset SearchAsciiZ ; We search for *.*
- Mov CX,10h ; Subdirectory attribute
- Mov AH,4Eh ; Find first file
- Int 21h ; by calling DOS
-
- Jmp Short TestMatch ; Hop around next section
- FindNextFile:
- Mov AH,4Fh ; Find next file
- Int 21h ; by calling DOS
- TestMatch:
- Jc NoMoreFiles ; If CY flag, at end of rope
-
- Mov BX,[DTAPointer] ; Our find stuff is here
- Test B [BX + 21],10h ; Test if directory attribute
- Jz FindNextFile ; If not, continue search
-
- Add BX,30 ; Now points to directory name
- Cmp Byte Ptr [BX],'.' ; Ignore "." and ".." entries
- Jz FindNextFile ; by continuing the search
-
- Cmp OneDeepFlag,1 ; looking only at this level?
- Je Compare
-
- Push BX ; save pointer to subdir name
-
- Mov DX,BX ; Now DX points to found dir
- Mov AH,3Bh ; Set up DOS function call
- Int 21h ; And change directory
-
- Pop BX ; get pointer to subdir name back
- Compare:
- Sub CX,CX
- Mov CX,Count
- Mov DI, Offset Sub_Dir
- Lea SI, BX
- Repe Cmpsb
-
- Jz Found ; matched up so leave
-
- Cmp OneDeepFlag,1
- Jne GoOn
- Mov [Direction],-1
- Jmp Short NextLevel
- GoOn:
- Add [DtaPointer],43 ; New DTA for new level
- Mov [Direction],0 ; I.E., Find first file
-
- Jmp NextLevel ; All ready to cycle through
-
- ; No More Files Found -- go back to previous level
- ; ------------------------------------------------
-
- NoMoreFiles:
- Cmp [DTAPointer],Offset DtaAreaBegin ; See if back at start
-
- Jz ExitGD ; If so, that's all, folks
-
- Sub [DTAPointer],43 ; Back one for previous
- Mov [Direction],-1 ; I.E., will find next file
-
- Mov DX,Offset BackOneDir ; The string ".."
- Mov AH,3Bh ; Call to change directory
- Int 21h ; Change directory to father
-
- Jmp NextLevel ; And continue the search
- Found:
- Cmp OneDeepFlag,1
- If ne Jmp Short F1
-
- Mov DX,BX ; Now DX points to found dir
- Mov AH,3Bh ; Set up DOS function call
- Int 21h ; And change directory
- F1:
- Mov Done_Flag,1
- ExitGD:
- Mov [Direction],0
- Pop ES,DI,SI
- Ret
-
- ;---------------------------------------------------------------------------;
- ; SetPath ;
- ;